package StampedLock_16;
import java.util.concurrent.locks.StampedLock;

public class 基本读写锁使用 {
    private static int sharedData = 0;
    private static final StampedLock lock = new StampedLock();
    private static final int READER_COUNT = 8;
    private static final int WRITER_COUNT = 2;

    public static void main(String[] args) {
        // 创建多个读取线程
        for (int i = 0; i < READER_COUNT; i++) {
            final int readerId = i;
            new Thread(new Runnable() {
                public void run() {
                    for (int j = 0; j < 3; j++) {
                        readData(readerId);
                        try {
                            Thread.sleep((long)(Math.random() * 100));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "Reader-" + i).start();
        }

        // 创建多个写入线程
        for (int i = 0; i < WRITER_COUNT; i++) {
            final int writerId = i;
            new Thread(new Runnable() {
                public void run() {
                    for (int j = 0; j < 2; j++) {
                        writeData(writerId, writerId * 10 + j);
                        try {
                            Thread.sleep((long)(Math.random() * 200));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "Writer-" + i).start();
        }
    }

    private static void readData(int readerId) {
        long stamp = lock.tryOptimisticRead(); // 尝试乐观读
        int currentData = sharedData;

        if (!lock.validate(stamp)) { // 检查乐观读期间是否有写操作
            stamp = lock.readLock(); // 退化为悲观读锁
            try {
                currentData = sharedData;
            } finally {
                lock.unlockRead(stamp);
            }
        }
        System.out.println(Thread.currentThread().getName() + " 读取数据: " + currentData);
    }

    private static void writeData(int writerId, int newValue) {
        long stamp = lock.writeLock(); // 获取写锁
        try {
            System.out.println(Thread.currentThread().getName() + " 开始写入");
            Thread.sleep(50); // 模拟写入耗时
            sharedData = newValue;
            System.out.println(Thread.currentThread().getName() + " 写入完成: " + newValue);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlockWrite(stamp);
        }
    }
}